home *** CD-ROM | disk | FTP | other *** search
/ TOS Silver 2000 / TOS Silver 2000.iso / programm / MM2_DEV / S / MOS / STORAGE.I < prev    next >
Encoding:
Text File  |  1992-02-17  |  34.2 KB  |  3 lines

  1. ⓪ IMPLEMENTATION MODULE Storage;⓪ (*$Y+,R-*)⓪ ⓪ (*-----------------------------------------------------------------------------⓪!* Copyright Januar 1989 Thomas Tempelmann⓪!*-----------------------------------------------------------------------------⓪!* Kurzbeschreibung : Auf StorBase aufgesetzte, systemunabhängige Memory-⓪!*                    verwaltung für MOS⓪!*-----------------------------------------------------------------------------⓪!* Systemversion : MOS 1.1⓪!* Textversion   : V#0293⓪!*-----------------------------------------------------------------------------⓪!* Datum    Vers  Autor  Bemerkung (Arbeitsbericht)⓪!*-----------------------------------------------------------------------------⓪!* 14.02.92  2.15 TT     'valid' benutzt Super() statt Supexec() wg. MiNT.⓪!* 10.11.90  2.14 TT     ALLOCATE/SysAlloc erkennt 0-size sofort⓪!* 08.11.90       TT     $R-⓪!* 26.10.90  2.13 TT     Neg. Überläufe bei size-Parm bei ALLOCATE/Enlarge weg.⓪!* 11.10.90  2.12 TT     StorBase.Resize-Aufruf gab zu viel frei.⓪!* 09.10.90  2.11 TT     DEALLOCATE gibt nix frei, wenn kein FullAcess und⓪!*                       size # 0; DEALLOCATE ruft ggf. Resize statt DEALLOCATE⓪!*                       in StorBase, damit shrink immer möglich ist.⓪!* 26.09.90  2.10 TT     MaxBlSize wird bei ACCs auf 2KB gesetzt, weil sonst⓪!*                       gleich meist 32K drauf gehen.⓪!* 19.08.90  2.9  TT     MemAvail macht keinen Overflow, wenn weniger als 40⓪!*                       Byte frei sind.⓪!* 29.07.90  2.8  TT     Available geändert.⓪!* 23.07.90  2.7  TT     ALLOCATE kann nun auch Speicher < MaxBlSize noch⓪!*                       anfordern, solange StorBase noch davon was übrig hat.⓪!* 15.07.90  2.6  TT     Kritische StorBase-Routinen werden nur bei⓪!*                       'FullStorBaseAccess' aufgerufen.⓪!* 13.06.90       TT     EnterSupervisorMode raus⓪!* 14.03.90  2.5  TT     ALOCATE/SysAlloc mit size=0 liefern NIL als Ptr.⓪!*                       (bisher wurde trotzdem ein Header alloziert);⓪!*                       MemAvail: BlockFullSize wird zusätzlich vom freien⓪!*                       Bereich abgezogen⓪!* 11.01.90  2.4  TT     Verify-Routine in Asm kodiert, prüft nun auch⓪!*                       Pointer auf Gültigkeit, sodaß kein Adr/Bus-Error⓪!*                       kommen kann; außerdem wird bei Erkennen eines⓪!*                       Fehlers die Speicherkette mit den noch intakten⓪!*                       Daten geschlossen⓪!* 07.07.89  2.3  TT     Optimierung einige Routinen in Asm⓪!* 05.06.89  2.3  TT     Nach Freigabe residenter Module wird nun nicht mehr⓪!*                       Speicherverw. inkonsistent. Grund: 'valid' erkennt nun,⓪!*                       wenn schon freigegebener Bereich nochmal freigegeben⓪!*                       wird.⓪!* 02.06.89  2.3  TT     More liefert ADR (Root) PROC (Resize) und PROC (Verify)⓪!* 14.05.89  2.2  TT     Es steckt noch ein Fehler entw. in MemSize oder⓪!*                       DEALLOCATE mit size>0!⓪!*                       Zur Sicherheit bei blockOK.ubNeg ANDI.L eingefügt⓪!*                       (weiß aber nicht, ob dies redundant ist).⓪!* 04.03.89  2.1  TT     getFree: full nicht erkannt, wenn origLen knapp unter⓪!*                         MaxBlSize lag. newBlock legte aber dann ggf. zuwenig⓪!*                         Speicher an.⓪!* 18.02.89  2.0  TT     1. Freigabe zum Testen (an Manuel, MAUS)⓪!*----------------------------------------------------------------------------*)⓪ ⓪ FROM SYSTEM IMPORT ASSEMBLER, WORD, LONGWORD, ADR, TSIZE, BYTE, ADDRESS;⓪ ⓪ FROM MOSGlobals IMPORT MemArea, InternalFault;⓪ ⓪ FROM MOSConfig IMPORT MaxBlSize;⓪ ⓪ FROM MOSSupport IMPORT ToSuper, ToUser;⓪ ⓪ FROM PrgCtrl IMPORT Accessory, EnvlpCarrier, TermCarrier, CatchProcessTerm,⓪(SetEnvelope;⓪ ⓪ IMPORT StorBase;⓪ ⓪ ⓪ TYPE⓪(PtrHead = POINTER TO Head;⓪ ⓪(HeadLink = RECORD⓪5n: INTEGER;  (* rel. offset von block.data *)⓪5p: INTEGER;  (* rel. offset von block.data *)⓪3END;⓪ ⓪(Head  = RECORD;           (* werden nur für used-Bereiche benutzt *)⓪2hd: HeadLink;⓪2root: INTEGER;  (* rel. Offset von Block.data (pos.Wert) *)⓪2level: INTEGER;⓪2size: INTEGER;  (* used-Größe, kann ungerade sein!     *)⓪B(* -- muß immer vor 'hd.data' stehen   *)⓪B(* damit 'fullBlk' funktioniert!       *)⓪2data: BYTE      (* Beginn der Daten *)⓪0END;⓪ CONST⓪(HeadSize = 10;            (* TSIZE (Head ohne data) *)⓪ ⓪ TYPE⓪(PtrLink = POINTER TO Link;⓪ ⓪(Link = RECORD⓪1next: PtrLink;⓪1prev: PtrLink;⓪/END;⓪ ⓪(PtrBlock = POINTER TO Block;⓪ ⓪(Block = RECORD⓪2blk: Link;⓪2size: LONGINT;  (* Größe des verfügbaren Bereichs *)⓪B(*  kann ungerade sein!           *)⓪B(* Bit 30: <full>                 *)⓪2CASE : CARDINAL OF⓪2| 0: (* full *)⓪4level: INTEGER;⓪4full: CARDINAL; (* = 0, wenn full *)⓪4fullData: BYTE⓪2| 1: (* root *)⓪4blRov: PtrBlock (* zeigt direkt auf letzten Block *)⓪2| 2: (* not full *)⓪4hd: HeadLink;⓪4hdRov: INTEGER; (* letzer hd, wo alloc durchgef. wurde *)⓪4free: LONGINT;  (* gesamter freier Bereich in Block *)⓪4hds : BYTE      (* Beginn der Header/Freibereiche *)⓪2END⓪0END;⓪ CONST⓪(BlockSize     = 22;  (* TSIZE (Block ohne hds) *)⓪(BlockFullSize = 16;  (* TSIZE (Block, 0) *)⓪ ⓪ ⓪ VAR Root: Block;⓪$StorLevel: INTEGER;  (* 0: Sys *)⓪$_membot, _memtop: ADDRESS;⓪ ⓪ ⓪ ⓪ PROCEDURE abs (bl: PtrBlock; hd: INTEGER): ADDRESS;⓪"(*$L-*)⓪"BEGIN⓪$ASSEMBLER⓪(; RETURN ADR (bl^.hds) + LONGCARD (LONG (hd))⓪(MOVE    -(A3),D0⓪(MOVE.L  -(A3),A0⓪(; ADDA.W  D0,A0⓪(; ADDA.W  #BlockSize,A0⓪(LEA     BlockSize(A0,D0.W),A0⓪(MOVE.L  A0,(A3)+⓪$END⓪"END abs;⓪"(*$L=*)⓪ ⓪ PROCEDURE rel (bl: PtrBlock; ad: ADDRESS): INTEGER;⓪"(*$L-*)⓪"BEGIN⓪$ASSEMBLER⓪(; RETURN SHORT ( ad - ADR (bl^.hds) )⓪(MOVE.L  -(A3),D0⓪(MOVE.L  -(A3),A0⓪(ADDA.W  #BlockSize,A0⓪(SUB.L   A0,D0⓪(MOVE.W  D0,(A3)+⓪$END⓪"END rel;⓪"(*$L=*)⓪ ⓪ ⓪ MODULE BlkLists;⓪ ⓪"IMPORT ASSEMBLER, abs, rel, ADR, Link, PtrBlock, HeadLink, BlockSize;⓪ ⓪"EXPORT linkBlkIn, linkBlkOut,⓪)linkHdIn, linkHdOut;⓪ ⓪ (*⓪"PROCEDURE linkBlkIn (VAR l, at: Link);⓪$BEGIN⓪(l.prev:= at.prev;⓪(l.next:= ADR (at);⓪(at.prev^.next:= ADR (l);⓪(at.prev:= ADR (l)⓪$END linkBlkIn;⓪ ⓪"PROCEDURE linkBlkOut (VAR l: Link);⓪$BEGIN⓪(l.prev^.next:= l.next;⓪(l.next^.prev:= l.prev⓪$END linkBlkOut;⓪ ⓪"PROCEDURE linkHdIn (bl: PtrBlock; VAR l: HeadLink; before: INTEGER);⓪$VAR at, at2: POINTER TO HeadLink;⓪$BEGIN⓪(at:= abs (bl, before);⓪(l.p:= at^.p;⓪(l.n:= before;⓪(at2:= abs (bl, at^.p);⓪(at2^.n:= rel (bl, ADR (l));⓪(at^.p:= rel (bl, ADR (l))⓪$END linkHdIn;⓪ ⓪"PROCEDURE linkHdOut (bl: PtrBlock; VAR l: HeadLink);⓪$VAR at: POINTER TO HeadLink;⓪$BEGIN⓪(at:= abs (bl, l.p);⓪(at^.n:= l.n;⓪(at:= abs (bl, l.n);⓪(at^.p:= l.p⓪$END linkHdOut;⓪ *)⓪ ⓪"(*$L-*)⓪ ⓪"PROCEDURE linkBlkIn (VAR l, at: Link);⓪$BEGIN⓪&ASSEMBLER⓪(; l.prev:= at.prev;⓪(; l.next:= ADR (at);⓪(; at.prev^.next:= ADR (l);⓪(; at.prev:= ADR (l)⓪(MOVE.L  -(A3),A1        ; ADR (at)⓪(MOVE.L  -(A3),A0        ; ADR (l)⓪(MOVE.L  Link.prev(A1),A2⓪(MOVE.L  A2,Link.prev(A0)⓪(MOVE.L  A1,Link.next(A0)⓪(MOVE.L  A0,Link.next(A2)⓪(MOVE.L  A0,Link.prev(A1)⓪&END⓪$END linkBlkIn;⓪ ⓪"PROCEDURE linkBlkOut (VAR l: Link);⓪$BEGIN⓪&ASSEMBLER⓪(; l.prev^.next:= l.next;⓪(; l.next^.prev:= l.prev⓪(MOVE.L  -(A3),A0        ; ADR (l)⓪(MOVE.L  Link.prev(A0),A1⓪(MOVE.L  Link.next(A0),A2⓪(MOVE.L  A2,Link.next(A1)⓪(MOVE.L  A1,Link.prev(A2)⓪&END⓪$END linkBlkOut;⓪ ⓪"PROCEDURE linkHdIn (bl: PtrBlock; VAR l: HeadLink; before: INTEGER);⓪$VAR at, at2: POINTER TO HeadLink;⓪$BEGIN⓪&ASSEMBLER⓪(MOVE    -(A3),D0        ; before⓪(MOVE.L  -(A3),A0        ; ADR (l)⓪(MOVE.L  -(A3),A1        ; bl⓪(; at:= abs (bl, before);⓪(; MOVE.L  A1,A2⓪(; ADDA.W  D0,A2⓪(; ADDA.W  #BlockSize,A2      ; at⓪(LEA     BlockSize(A1,D0.W),A2⓪(; l.p:= at^.p;⓪(MOVE.W  HeadLink.p(A2),D1  ; at^.p⓪(MOVE.W  D1,HeadLink.p(A0)⓪(; l.n:= before;⓪(MOVE.W  D0,HeadLink.n(A0)⓪(; BERECHNE rel (bl, ADR (l)) NACH A0⓪(ADDA.W  #BlockSize,A1⓪(SUBA.L  A1,A0⓪(; at2:= abs (bl, at^.p);⓪(ADDA.W  D1,A1              ; at2⓪(; at2^.n:= rel (bl, ADR (l));⓪(; at^.p:= rel (bl, ADR (l))⓪(MOVE.W  A0,HeadLink.n(A1)⓪(MOVE.W  A0,HeadLink.p(A2)⓪&END⓪$END linkHdIn;⓪ ⓪"PROCEDURE linkHdOut (bl: PtrBlock; VAR l: HeadLink);⓪$VAR at: POINTER TO HeadLink;⓪$BEGIN⓪&ASSEMBLER⓪(MOVE.L  -(A3),A0        ; ADR (l)⓪(MOVE.L  -(A3),A1        ; bl⓪(; at:= abs (bl, l.p);⓪(MOVE.L  A1,A2⓪(ADDA.W  HeadLink.p(A0),A2⓪(ADDA.W  #BlockSize,A2      ; at⓪(; at^.n:= l.n;⓪(MOVE.W  HeadLink.n(A0),HeadLink.n(A2)⓪(; at:= abs (bl, l.n);⓪(ADDA.W  HeadLink.n(A0),A1⓪(ADDA.W  #BlockSize,A1      ; at⓪(; at^.p:= l.p⓪(MOVE.W  HeadLink.p(A0),HeadLink.p(A1)⓪&END⓪$END linkHdOut;⓪ ⓪"(*$L=*)⓪ ⓪"END BlkLists;⓪ ⓪ ⓪ PROCEDURE setBit6 (VAR i: ARRAY OF BYTE);⓪"(*$L-*)⓪"BEGIN⓪$ASSEMBLER⓪(SUBQ.L  #2,A3⓪(MOVEA.L -(A3),A0⓪(BSET.B  #6,(A0)⓪$END⓪"END setBit6;⓪"(*$L=*)⓪ ⓪ PROCEDURE blkFull (bl: PtrBlock): BOOLEAN;⓪"(*$L-*)⓪"BEGIN⓪$ASSEMBLER⓪(MOVE.L  -(A3),A0⓪(BTST    #6,Block.size(A0)⓪(SNE     D0⓪(ANDI    #1,D0⓪(MOVE    D0,(A3)+⓪$END⓪"END blkFull;⓪"(*$L=*)⓪ ⓪ PROCEDURE blkSize (bl: PtrBlock): LONGINT;⓪"(*$L-*)⓪"BEGIN⓪$ASSEMBLER⓪(MOVE.L  -(A3),A0⓪(MOVE.L  Block.size(A0),D0⓪(ANDI.L  #$00FFFFFF,D0⓪(MOVE.L  D0,(A3)+⓪$END⓪"END blkSize;⓪"(*$L=*)⓪ ⓪ PROCEDURE sizeHd (bl: PtrBlock; hd: INTEGER): INTEGER;⓪"(*$L-*)⓪"BEGIN⓪$ASSEMBLER⓪(; hdp:= abs (bl, hd);⓪(; RETURN val (hdp^.size)⓪(MOVE    -(A3),D0⓪(MOVE.L  -(A3),A0⓪(MOVE.W  Head.size+BlockSize(A0,D0.W),D0⓪(ADDQ    #1,D0⓪(ANDI    #$FFFE,D0⓪(MOVE    D0,(A3)+⓪$END;⓪"END sizeHd;⓪"(*$L=*)⓪ ⓪ PROCEDURE nextHd (bl: PtrBlock; hd: INTEGER): INTEGER;⓪"(*$L-*)⓪"BEGIN⓪$ASSEMBLER⓪(; hdp:= abs (bl, hd);⓪(; RETURN hdp^.hd.n⓪(MOVE    -(A3),D0⓪(MOVE.L  -(A3),A0⓪(MOVE.W  Head.hd.n+BlockSize(A0,D0.W),(A3)+⓪$END;⓪"END nextHd;⓪"(*$L=*)⓪ ⓪ PROCEDURE prevHd (bl: PtrBlock; hd: INTEGER): INTEGER;⓪"(*$L-*)⓪"BEGIN⓪$ASSEMBLER⓪(; hdp:= abs (bl, hd);⓪(; RETURN hdp^.hd.p⓪(MOVE    -(A3),D0⓪(MOVE.L  -(A3),A0⓪(MOVE.W  Head.hd.p+BlockSize(A0,D0.W),(A3)+⓪$END;⓪"END prevHd;⓪"(*$L=*)⓪ ⓪ ⓪ PROCEDURE valid (ad: ADDRESS; VAR bl: PtrBlock;⓪2VAR hd: PtrHead; VAR full: BOOLEAN): BOOLEAN;⓪"(* Verkettung prüfen und ggf. 'bl' und 'full' setzen *)⓪"(*$L-*)⓪"BEGIN⓪$(*⓪&IF ad = NIL THEN RETURN FALSE END;⓪&full:= fullBlk (ad);⓪&IF full THEN⓪(bl:= ad - LONG (BlockFullSize);⓪&ELSE⓪(hd:= ad - LONG (HeadSize);⓪(bl:= ADDRESS (hd) - LONGCARD (LONG (hd^.root + BlockSize));⓪(IF nextHd (bl, hd.p)) # prevHd (bl, hd.n)) # hd THEN⓪*RETURN FALSE⓪(END⓪&END;⓪&RETURN bl^.blk.next^.prev = bl^.blk.prev^.next⓪$*)⓪$ASSEMBLER⓪(SUBQ.L  #4,A7⓪(JSR     ToSuper⓪ ⓪(MOVE.L  8,-(A7)         ; bus error vector⓪(MOVE.L  12,-(A7)        ; address error vector⓪(LEA     inval(PC),A0⓪(MOVE.L  A0,8⓪(MOVE.L  A0,12⓪(MOVE.L  A7,D1⓪(⓪(MOVE.L  -(A3),A2        ; full⓪(MOVE.L  -(A3),D2        ; hd⓪(MOVE.L  -(A3),A1        ; bl⓪(MOVE.L  -(A3),A0        ; ad⓪(⓪(MOVE.L  A0,D0⓪(BEQ     inval⓪(⓪(TST.W   -2(A0)          ; bei <full> ist 'hd.size' = 0⓪(SEQ     D0⓪(ANDI    #1,D0⓪(MOVE    D0,(A2)         ; full setzen⓪(⓪(BEQ     notfull⓪(⓪(; bl:= ad - LONG (BlockFullSize)⓪(MOVE.L  A0,A2⓪(SUBA.W  #BlockFullSize,A2⓪(MOVE.L  A2,(A1)⓪(BRA     fullend⓪(⓪¬full⓪(; hd:= ad - LONG (HeadSize);⓪(MOVE.L  A0,A2⓪(SUBA.W  #HeadSize,A2⓪(MOVE.L  D2,A0⓪(MOVE.L  A2,(A0)⓪(; bl:= ADDRESS (hd) - LONGCARD (LONG (hd^.root + BlockSize));⓪(MOVE.L  A2,A0                   ; hd retten⓪(SUBA.W  Head.root(A2),A2⓪(SUBA.W  #BlockSize,A2⓪(MOVE.L  A2,(A1)⓪(⓪(; rel (bl, hd):⓪(MOVE.L  A0,D2           ; hd⓪(MOVE.L  A2,A1           ; bl⓪(ADDA.W  #BlockSize,A1⓪(SUB.L   A1,D2⓪(; IF nextHd (bl, hd.p)) # prevHd (bl, hd.n)) # rel (bl, hd) THEN⓪(MOVE.W  Head.hd.p(A0),D0⓪(CMP.W   Head.hd.n+BlockSize(A2,D0.W),D2⓪(BNE     inval⓪(MOVE.W  Head.hd.n(A0),D0⓪(CMP.W   Head.hd.p+BlockSize(A2,D0.W),D2⓪(BNE     inval⓪(⓪&fullend⓪(; RETURN bl^.blk.next^.prev = bl^.blk.prev^.next⓪(MOVE.L  Block.blk.next(A2),A1⓪(MOVE.L  Block.blk.prev(A1),D0⓪(MOVE.L  Block.blk.prev(A2),A1⓪(CMP.L   Block.blk.next(A1),D0⓪(SEQ     D0⓪(ANDI    #1,D0⓪(MOVE    D0,(A3)+⓪(BRA     ende⓪&inval:⓪(CLR     (A3)+⓪(MOVE.L  D1,A7⓪&ende:⓪(MOVE.L  (A7)+,12⓪(MOVE.L  (A7)+,8⓪(⓪(JSR     ToUser⓪(ADDQ.L  #4,A7⓪$END⓪"END valid;⓪"(*$L=*)⓪ ⓪ PROCEDURE incHdSize (hd: PtrHead; siz: CARDINAL);⓪"(*$L-*)⓪"BEGIN⓪$ASSEMBLER⓪(MOVE.W  -(A3),D0⓪(MOVE.L  -(A3),A0⓪(ADD.W   D0,Head.size(A0)⓪$END⓪"END incHdSize;⓪"(*$L=*)⓪ ⓪ PROCEDURE decHdSize (hd: PtrHead; siz: CARDINAL);⓪"(*$L-*)⓪"BEGIN⓪$ASSEMBLER⓪(MOVE.W  -(A3),D0⓪(MOVE.L  -(A3),A0⓪(SUB.W   D0,Head.size(A0)⓪$END⓪"END decHdSize;⓪"(*$L=*)⓪ ⓪ PROCEDURE resize (VAR ad: ADDRESS; len: LONGINT): BOOLEAN;⓪"(*⓪#* 'len': wenn pos, dann Abzugswert; wenn neg., dann Vergrößerungsoffset;⓪#*   wenn Null, dann ganz freigeben.⓪#* 'ad' bleibt unverändert, wenn RETURN FALSE⓪#*)⓪ ⓪"VAR hd: PtrHead; bl: PtrBlock; ok, full: BOOLEAN;⓪&i: CARDINAL;⓪ ⓪"PROCEDURE blkAway;⓪$BEGIN⓪&IF Root.blRov = bl THEN Root.blRov:= NIL END;⓪&linkBlkOut (bl^.blk);⓪&StorBase.DEALLOCATE (bl, 0)⓪$END blkAway;⓪ ⓪"VAR this, freeEnd, freeBeg: INTEGER;⓪&dumusedbeg, duml, dumfreebeg: INTEGER;⓪ ⓪"BEGIN (* resize *)⓪$IF NOT valid (ad,bl,hd,full) THEN⓪&RETURN FALSE⓪$END;⓪$IF full THEN⓪&(* <full> block: ad zeigt hinter Block(0) *)⓪&IF len < 0L THEN⓪((* Block um 'len' vergrößern *)⓪(IF StorBase.FullStorBaseAccess () THEN⓪*StorBase.Enlarge (bl, -len, ok);⓪*IF ok THEN bl^.size:= bl^.size + ABS (len) END;⓪*RETURN ok⓪(ELSE⓪*RETURN FALSE⓪(END⓪&ELSIF (len > 0L) AND (len < blkSize (bl)) THEN⓪((* shrink only *)⓪(bl^.size:= bl^.size - len;⓪((* Blockgröße neu setzen. Plus den Block-Header und aufrunden: *)⓪(StorBase.Resize (bl, (BlockFullSize + blkSize (bl) + 1) DIV 2 * 2, ok);⓪(RETURN ok⓪&ELSE⓪(blkAway;⓪(ad:= NIL⓪&END⓪$ELSE (* NOT full: *)⓪&(* ad zeigt hinter Header *)⓪&IF len < 0L THEN⓪((* Block um 'len' vergrößern *)⓪(this:= rel (bl, hd);⓪(freeEnd:= nextHd (bl, this);⓪(IF freeEnd < 0 THEN freeEnd:= SHORT (blkSize (bl)) END;⓪(freeBeg:= this + HeadSize + sizeHd (bl, this);⓪(IF ABS (len) <= LONG (freeEnd - freeBeg) THEN⓪*i:= SHORT (ABS (len));⓪*incHdSize (hd, i);⓪*DEC (bl^.free, (ORD (ODD (hd^.size)) + i) DIV 2 * 2)⓪(ELSE⓪*RETURN FALSE⓪(END⓪&ELSIF (len > 0L) AND (len < LONG (hd^.size)) THEN⓪((* shrink only *)⓪(i:= SHORT (len);⓪(decHdSize (hd, i);⓪(INC (bl^.free, (ORD (NOT ODD (hd^.size)) + i) DIV 2 * 2)⓪&ELSE⓪(i:= hd^.size + HeadSize;⓪(IF ODD (i) THEN INC (i) END;⓪(INC (bl^.free, i);⓪(IF bl^.hdRov = rel (bl, hd) THEN⓪*bl^.hdRov:= prevHd (bl, bl^.hdRov)⓪(END;⓪(linkHdOut (bl, hd^.hd);⓪(IF bl^.free = blkSize (bl) THEN blkAway END;⓪((*⓪*IF hd^.size = 966 THEN⓪,WriteLn;⓪,WriteString ('bl^.size: '); WriteString (CardToStr (bl^.size,0)); WriteLn;⓪,WriteString ('bl^.free: '); WriteString (CardToStr (bl^.free,0)); WriteLn;⓪,dumfreebeg:= 0;            (* End of last used area *)⓪,dumusedbeg:= bl^.hd.n;     (* Start of new used area *)⓪,LOOP⓪.IF dumusedbeg < 0 THEN⓪0duml:= VAL (INTEGER, blkSize (bl)) - dumfreebeg;⓪0IF duml > 0 THEN WriteString ('free: '); WriteString (IntToStr (duml,8)); WriteString (IntToStr (nextHd(bl,dumusedbeg),8)); WriteString (IntToStr (prevHd(bl,dumusedbeg),8)); WriteLn; END;⓪0EXIT⓪.ELSE⓪0duml:= dumusedbeg - dumfreebeg;⓪0IF duml > 0 THEN WriteString ('free: '); WriteString (IntToStr (duml,8)); WriteString (IntToStr (nextHd(bl,dumusedbeg),8)); WriteString (IntToStr (prevHd(bl,dumusedbeg),8)); WriteLn END;⓪.END;⓪.WriteString ('used: ');⓪.WriteString (IntToStr (sizeHd (bl, dumusedbeg),8));⓪.WriteString (IntToStr (nextHd(bl,dumusedbeg),8));⓪.WriteString (IntToStr (prevHd(bl,dumusedbeg),8));⓪.WriteLn;⓪.dumfreebeg:= dumusedbeg + HeadSize + sizeHd (bl, dumusedbeg);⓪.dumusedbeg:= nextHd (bl, dumusedbeg)⓪,END;⓪*END;⓪(*)⓪(ad:= NIL⓪&END;⓪$END;⓪$RETURN TRUE⓪"END resize;⓪ ⓪ PROCEDURE blockOK (VAR freeBeg, usedBeg: INTEGER;⓪3neededLen: LONGINT; bl: PtrBlock): BOOLEAN;⓪"(*$L-*)⓪"(* freien Bereich im Block 'bl' suchen *)⓪"VAR end: INTEGER;⓪&hd: PtrHead;⓪"BEGIN⓪$ASSEMBLER⓪((*⓪*end:= bl^.hdRov;⓪*usedBeg:= nextHd (bl, end);  (* Start of new used area *)⓪*IF end < 0 THEN⓪,freeBeg:= 0;               (* End of last used area *)⓪*ELSE⓪,freeBeg:= end + HeadSize + sizeHd (bl, end);⓪*END;⓪*LOOP⓪,IF usedBeg < 0 THEN⓪.IF (SHORT (blkSize (bl)) - freeBeg) >= SHORT (neededLen) THEN EXIT END;⓪,ELSE⓪.IF (usedBeg - freeBeg) >= SHORT (neededLen) THEN EXIT END⓪,END;⓪,IF usedBeg = end THEN RETURN FALSE END;⓪,IF usedBeg < 0 THEN⓪.freeBeg:= 0⓪,ELSE⓪.freeBeg:= usedBeg + HeadSize + sizeHd (bl, usedBeg)⓪,END;⓪,usedBeg:= nextHd (bl, usedBeg)⓪*END;⓪*RETURN TRUE⓪(*)⓪(MOVEM.L D3-D6/A4/A5,-(A7)⓪ ⓪(MOVE.L  -(A3),A5                        ; A5: bl⓪ ⓪(; end:= bl^.hdRov⓪(MOVE.W  Block.hdRov(A5),D3              ; D3: end⓪ ⓪(; usedBeg:= nextHd (bl, end)⓪(MOVE.W  Head.hd.n+BlockSize(A5,D3.W),D4 ; D4: usedBeg⓪ ⓪(; IF end < 0 THEN freeBeg:= 0 ELSE⓪(;    freeBeg:= end + HeadSize + sizeHd (bl, end) END;⓪(CLR.W   D5                              ; D5: freeBeg⓪(TST.W   D3⓪(BMI     endNeg⓪(MOVE    D3,D5⓪(ADDI.W  #HeadSize+1,D5⓪(ADD.W   Head.size+BlockSize(A5,D3.W),D5⓪(ANDI    #$FFFE,D5⓪&endNeg:⓪ ⓪(MOVE.L  -(A3),D6                        ; D6: neededLen⓪ ⓪(MOVEQ   #HeadSize+1,D1⓪(MOVE    #$FFFE,D2⓪ ⓪&loop1:⓪(TST     D4⓪(BMI     ubNeg⓪ ⓪&ubPos:⓪(MOVE    D4,D0⓪(SUB.W   D5,D0⓪(CMP.W   D6,D0⓪(BCC     retTRUE⓪(CMP     D3,D4⓪(BEQ     retFALSE⓪(MOVE    D4,D5⓪(ADD.W   D1,D5⓪(ADD.W   Head.size+BlockSize(A5,D4.W),D5⓪(AND     D2,D5⓪(MOVE.W  Head.hd.n+BlockSize(A5,D4.W),D4⓪(BPL     ubPos⓪ ⓪&ubNeg:⓪(MOVE.L  Block.size(A5),D0⓪(ANDI.L  #$00FFFFFF,D0⓪(SUB.W   D5,D0⓪(CMP.W   D6,D0⓪(BCC     retTRUE⓪(CMP     D3,D4⓪(BEQ     retFALSE⓪(CLR     D5⓪(MOVE.W  Head.hd.n+BlockSize(A5,D4.W),D4⓪(BRA     loop1⓪ ⓪&retFALSE:⓪(CLR     D0⓪(BRA     return⓪ ⓪&retTRUE:⓪(MOVEQ   #1,D0⓪ ⓪&return:⓪(MOVE.L  -(A3),A0                ; ADR (usedBeg)⓪(MOVE    D4,(A0)⓪(MOVE.L  -(A3),A0                ; ADR (freeBeg)⓪(MOVE    D5,(A0)⓪(MOVEM.L (A7)+,D3-D6/A4/A5⓪(MOVE    D0,(A3)+⓪$END⓪"END blockOK;⓪"(*$L=*)⓪ ⓪ ⓪ PROCEDURE getFree (origLen: LONGINT; VAR neededLen: LONGINT; VAR full: BOOLEAN;⓪3VAR blSize: LONGINT; VAR bl: PtrBlock;⓪3VAR usedBeg, freeBeg: INTEGER): BOOLEAN;⓪ ⓪"VAR bl0: PtrBlock;⓪ ⓪"BEGIN (* getFree *)⓪$neededLen:= origLen;⓪$IF ODD (neededLen) THEN INC (neededLen) END;⓪$full:= (neededLen + LONG(HeadSize)) >= MaxBlSize;⓪$IF NOT full THEN⓪&INC (neededLen, HeadSize); (* der Head muß nun auf jeden Fall rein *)⓪&bl0:= Root.blRov;⓪&IF bl0 = NIL THEN bl0:= ADDRESS (Root.blk.next) END;⓪&bl:= bl0;⓪&REPEAT                (* alle Blocks nach freiem Platz durchsuchen *)⓪(IF (bl # ADR (Root))⓪(AND NOT blkFull (bl)⓪(AND (bl^.free >= neededLen) THEN⓪*IF blockOK (freeBeg, usedBeg, neededLen, bl) THEN⓪,RETURN TRUE⓪*END⓪(END;⓪(bl:= ADDRESS (bl^.blk.next)⓪&UNTIL bl = bl0;⓪&blSize:= MaxBlSize + LONG (BlockSize)⓪$ELSE⓪&blSize:= neededLen + LONG (BlockFullSize)⓪$END;⓪$RETURN FALSE⓪"END getFree;⓪ ⓪ ⓪ PROCEDURE alloc (origLen: LONGINT; level: INTEGER): ADDRESS;⓪ ⓪"VAR freeBeg, usedBeg: INTEGER;⓪&bl: PtrBlock;⓪&blSize, neededLen: LONGINT;⓪&full: BOOLEAN;⓪ ⓪"PROCEDURE newBlock (): BOOLEAN;⓪$BEGIN⓪&StorBase.SysAlloc (bl, blSize);⓪&IF bl = NIL THEN RETURN FALSE END;⓪&IF full THEN⓪(linkBlkIn (bl^.blk, Root.blk);⓪(bl^.size:= origLen;⓪(bl^.level:= level;⓪(setBit6 (bl^.size);        (* full-Kennung *)⓪(bl^.full:= 0;              (* full-Kennung *)⓪&ELSE⓪(WITH bl^ DO⓪*linkBlkIn (blk, Root.blk);⓪*size:= MaxBlSize;  (* 'size' enth. Größe des verfügbaren Bereichs *)⓪*free:= size;⓪*hd.n:= rel (bl, ADR (hd));⓪*hd.p:= hd.n;⓪*hdRov:= hd.n⓪(END⓪&END;⓪&Root.blRov := bl;⓪&RETURN TRUE⓪$END newBlock;⓪ ⓪"PROCEDURE insert (): ADDRESS;⓪$(* Bereich belegen *)⓪$VAR hd: PtrHead;⓪$BEGIN⓪&(* 'bl' zeigt auf Block, der freien Bereich enthält *)⓪&hd:= abs (bl, freeBeg);⓪&hd^.size:= SHORT (origLen);⓪&hd^.level:= level;⓪&linkHdIn (bl, hd^.hd, usedBeg);⓪&hd^.root:= freeBeg;⓪&DEC (bl^.free, CARDINAL (SHORT (neededLen))); (* origLen + HeadSize *)⓪&bl^.hdRov:= freeBeg;⓪&Root.blRov := bl;⓪&RETURN ADR (hd^.data)⓪$END insert;⓪ ⓪"VAR lastMax: LONGCARD;⓪ ⓪"BEGIN (* alloc *)⓪$IF origLen = 0L THEN⓪&RETURN NIL⓪$END;⓪$IF getFree (origLen, neededLen, full, blSize, bl, usedBeg, freeBeg) THEN⓪&RETURN insert ()⓪$END;⓪$IF NOT newBlock () THEN⓪&IF full THEN RETURN NIL END;⓪&(*⓪'* wenn weniger als MaxBlSize benötigt, aber nicht mehr Platz für⓪'* einen ganzen neuen Verwaltungsblock da ist, dann eben einen⓪'* full-Block mit der benötigten Size anfordern.⓪'*)⓪&lastMax:= MaxBlSize;⓪&MaxBlSize:= origLen;      (* full-Block erzwingen *)⓪&IF getFree (origLen, neededLen, full, blSize, bl, usedBeg, freeBeg) THEN⓪((* muß FALSE liefern *)⓪&END;⓪&MaxBlSize:= lastMax;⓪&IF NOT newBlock () THEN RETURN NIL END⓪$END;⓪$IF full THEN RETURN ADR (bl^.fullData) END;⓪$IF NOT blockOK (freeBeg, usedBeg, neededLen, bl) THEN⓪&ASSEMBLER⓪(TRAP    #6⓪(DC.W    InternalFault-$C000     ; text follows, caller caused⓪(ACZ     'Storage allocation error'⓪(SYNC⓪&END⓪$END;⓪$RETURN insert ()⓪"END alloc;⓪ ⓪ PROCEDURE Verify (): CARDINAL;⓪"(*⓪#* Liefert 0, wenn alle Block- und Head-Verkettungen OK sind⓪#*⓪#* VORSICHT: Da auch full-Blocks angelegt werden können, die⓪#*   kleiner als MaxBlSize sind, keinesfalls full-Blocks⓪#*   dahingehend prüfen!⓪#*)⓪ ⓪"(* VAR bl: PtrBlock; hd: PtrHead; freeBeg, usedBeg: INTEGER; l: LONGINT; *)⓪"VAR result: CARDINAL;⓪ ⓪ (*$R-*)⓪"BEGIN⓪$ASSEMBLER⓪(LEA     Root,A0⓪(BRA     loop1⓪&err1⓪(BRA.W   errEnd⓪&loop1⓪(MOVE.L  Block.blk.next(A0),A0⓪(MOVE.L  A0,D0⓪(BTST    #0,D0           ; ungerade?⓪(BNE     err1⓪((* das geht nicht im Fast-RAM des TT!!!⓪*CMPA.L  _membot,A0      ; < membot?⓪*BCS     err1⓪*CMPA.L  _memtop,A0      ; > memtop?⓪*BCC     err1⓪(*)⓪(CMPA.L  #Root,A0⓪(BEQ.W   exit1           ; ende ? -> OK⓪(BTST    #6,Block.size(A0)⓪(BEQ     notFull⓪(TST.L   Block.size(A0)⓪(BMI     err1⓪(MOVE.W  Block.level(A0),D0⓪(CMP.W   StorLevel,D0⓪(BHI     err1⓪(TST.W   Block.full(A0)⓪(BNE     err1⓪(BRA     loop1⓪¬Full⓪(; IF bl^.size > (MaxBlSize + LONG (BlockSize)) THEN RETURN 4 END;⓪(MOVE.L  Block.size(A0),D1⓪ (*  *** das darf nicht geprüft werden, weil MaxBlSize variieren kann! ***⓪(MOVE.L  MaxBlSize,D0⓪(ADDI.L  #BlockSize,D0⓪(CMP.L   D0,D1⓪(BHI     err1⓪ *)⓪(; IF bl^.free >= bl^.size THEN RETURN 18 END;⓪(MOVE.L  Block.free(A0),D0⓪(CMP.L   D1,D0⓪(BCC     err1⓪(; IF ODD (bl^.size) THEN RETURN 5 END;⓪(BTST    #0,D1⓪(BNE     err1⓪(; hd:= abs (bl, bl^.hdRov);⓪(MOVE.W  Block.hdRov(A0),D0⓪(BTST    #0,D0⓪(BNE     err1⓪(LEA     BlockSize(A0,D0.W),A2⓪(; IF hd^.root # bl^.hdRov THEN RETURN 6 END;⓪(CMP.W   Head.root(A2),D0⓪(BNE     err1⓪(⓪(; usedBeg:= bl^.hd.n;⓪(MOVE.W  Block.hd.n(A0),D1       ; usedBeg⓪(; l:= 0;⓪(CLR.W   -(A7)                   ; l⓪(BRA     loop2⓪&err2⓪(ADDQ.L  #2,A7⓪(BRA     err1⓪&loop2⓪(; IF ODD (usedBeg) THEN RETURN 7 END;⓪(BTST    #0,D1⓪(BNE     err2⓪(; IF usedBeg < 0 THEN⓪(TST.W   D1⓪(BPL     notNeg⓪(;   IF usedBeg # rel (bl, ADR (bl^.hd)) THEN RETURN 8 END;⓪(CMPI.W  #$FFF6,D1⓪(BNE     err2⓪(;   EXIT⓪(BRA     exit2⓪(; END;⓪¬Neg⓪(; hd:= abs (bl, usedBeg);⓪(LEA     BlockSize(A0,D1.W),A2⓪(; IF prevHd (bl, nextHd (bl, usedBeg)) # usedBeg THEN RETURN 20 END;⓪(; IF ODD (nextHd (bl, usedBeg)) THEN RETURN 14 END;⓪(MOVE.W  Head.hd.n+BlockSize(A0,D1.W),D2⓪(BTST    #0,D2⓪(BNE     err2⓪(CMP.W   Head.hd.p+BlockSize(A0,D2.W),D1⓪(BNE     err2⓪(; IF nextHd (bl, prevHd (bl, usedBeg)) # usedBeg THEN RETURN 19 END;⓪(; IF ODD (prevHd (bl, usedBeg)) THEN RETURN 15 END;⓪(MOVE.W  Head.hd.p+BlockSize(A0,D1.W),D2⓪(BTST    #0,D2⓪(BNE     err2⓪(CMP.W   Head.hd.n+BlockSize(A0,D2.W),D1⓪(BNE     err2⓪(; IF hd^.size < 0 THEN RETURN 9 END;⓪(MOVEQ   #0,D2⓪(MOVE.W  Head.size(A2),D2⓪(BLE     err2                    ; hd.size <= 0 ?⓪(; IF LONG (hd^.size) > bl^.size THEN RETURN 10 END;⓪(CMP.L   Block.size(A0),D2⓪(BHI     err2⓪(; IF hd^.level > StorLevel THEN RETURN 11 END;⓪(MOVE.W  Head.level(A2),D0⓪(CMP.W   StorLevel,D0⓪(BHI     err2⓪(; IF hd^.root # usedBeg THEN RETURN 12 END;⓪(CMP.W   Head.root(A2),D1⓪(BNE     err2⓪(; INC (l, HeadSize+CARDINAL (hd^.size));⓪(; IF ODD (hd^.size) THEN INC (l) END;⓪(ADDI.W  #HeadSize,D2⓪(ADDQ    #1,D2⓪(BCLR    #0,D2⓪(ADD.W   D2,(A7)⓪(BCS     err2⓪((* macht keinen Sinn, weil 'sizeHd' sowieso Sync macht:⓪*; freeBeg:= usedBeg + HeadSize + sizeHd (bl, usedBeg);⓪*; IF ODD (freeBeg) THEN RETURN 13 END;⓪(*)⓪(; usedBeg:= nextHd (bl, usedBeg)⓪(MOVE.W  Head.hd.n+BlockSize(A0,D1.W),D1⓪(BRA     loop2⓪&exit2⓪(; IF (bl^.size-l) # bl^.free THEN RETURN 17 END⓪(MOVE.L  Block.size(A0),D0⓪(MOVEQ   #0,D2⓪(MOVE.W  (A7)+,D2⓪(SUB.L   D2,D0⓪(CMP.L   Block.free(A0),D0⓪(BEQ     loop1⓪&errEnd⓪(LEA     Root,A0⓪(MOVE.L  A0,Block.blk.next(A0)  ; Liste retten, indem Liste geleert wird⓪(MOVE.L  A0,Block.blk.prev(A0)⓪(CLR.L   Block.blRov(A0)⓪(MOVEQ   #1,D0⓪(BRA     ende⓪&exit1⓪(MOVEQ   #0,D0⓪&ende⓪(MOVE    D0,result(A6)⓪$END;⓪$RETURN result⓪ (*⓪$bl:= ADR (Root);⓪$LOOP⓪&bl:= ADDRESS (bl^.blk.next);⓪&IF bl = ADR (Root) THEN EXIT END;⓪&IF blkFull (bl) THEN⓪((* Block-Werte prüfen *)⓪(IF bl^.size < 0L THEN RETURN 1 END;⓪(IF bl^.level > StorLevel THEN RETURN 2 END;⓪(IF bl^.full # 0 THEN RETURN 3 END;⓪&ELSE⓪((* Block-Werte prüfen *)⓪((*** das darf nicht geprüft werden, weil MaxBlSize variieren kann! ***⓪*IF bl^.size > (MaxBlSize + LONG (BlockSize)) THEN RETURN 4 END;⓪(*)⓪(IF bl^.free >= bl^.size THEN RETURN 18 END;⓪(IF ODD (bl^.size) THEN RETURN 5 END;⓪(hd:= abs (bl, bl^.hdRov);⓪(IF hd^.root # bl^.hdRov THEN RETURN 6 END;⓪(usedBeg:= bl^.hd.n;     (* Start of new used area *)⓪(l:= 0;⓪(LOOP⓪*IF ODD (usedBeg) THEN RETURN 7 END;⓪*IF usedBeg < 0 THEN⓪,IF usedBeg # rel (bl, ADR (bl^.hd)) THEN RETURN 8 END;⓪,EXIT⓪*END;⓪*hd:= abs (bl, usedBeg);⓪*(* Head prüfen *)⓪*IF nextHd (bl, prevHd (bl, usedBeg)) # usedBeg THEN RETURN 19 END;⓪*IF prevHd (bl, nextHd (bl, usedBeg)) # usedBeg THEN RETURN 20 END;⓪*IF hd^.size < 0 THEN RETURN 9 END;⓪*IF LONG (hd^.size) > bl^.size THEN RETURN 10 END;⓪*IF hd^.level > StorLevel THEN RETURN 11 END;⓪*IF hd^.root # usedBeg THEN RETURN 12 END;⓪*INC (l, HeadSize+CARDINAL (hd^.size));⓪*IF ODD (hd^.size) THEN INC (l) END;⓪*freeBeg:= usedBeg + HeadSize + sizeHd (bl, usedBeg);⓪*IF ODD (freeBeg) THEN RETURN 13 END;⓪*IF ODD (nextHd (bl, usedBeg)) THEN RETURN 14 END;⓪*IF ODD (prevHd (bl, usedBeg)) THEN RETURN 15 END;⓪*IF nextHd (bl, prevHd (bl, usedBeg))⓪+# prevHd (bl, nextHd (bl, usedBeg)) THEN RETURN 16 END;⓪*usedBeg:= nextHd (bl, usedBeg)⓪(END;⓪(IF (bl^.size-l) # bl^.free THEN RETURN 17 END⓪&END;⓪$END;⓪$RETURN 0⓪ *)⓪"END Verify;⓪ (*$R=*)⓪ ⓪ ⓪ PROCEDURE Inconsistent (): BOOLEAN;⓪"BEGIN⓪$RETURN StorBase.Inconsistent () OR (Verify () # 0)⓪"END Inconsistent;⓪ ⓪ ⓪ PROCEDURE ALLOCATE ( VAR addr: ADDRESS; size: LONGCARD );⓪"(*$L-*)⓪"BEGIN⓪$ASSEMBLER⓪(; addr:= alloc (size, StorLevel);⓪(CLR.L   D0⓪(MOVE.L  -(A3),D1        ; size⓪(BLE     error⓪(MOVE.L  D1,(A3)+⓪(MOVE    StorLevel,(A3)+⓪(JSR     alloc⓪(MOVE.L  -(A3),D0⓪&error⓪(MOVE.L  -(A3),A0        ; addr⓪(MOVE.L  D0,(A0)⓪$END;⓪"END ALLOCATE;⓪"(*$L=*)⓪ ⓪ PROCEDURE SysAlloc ( VAR addr: ADDRESS; size: LONGCARD );⓪"(*$L-*)⓪"BEGIN⓪$ASSEMBLER⓪(; addr:= alloc (size, 0);⓪(CLR.L   D0⓪(MOVE.L  -(A3),D1        ; size⓪(BLE     error⓪(MOVE.L  D1,(A3)+⓪(CLR     (A3)+⓪(JSR     alloc⓪(MOVE.L  -(A3),D0⓪&error⓪(MOVE.L  -(A3),A0        ; addr⓪(MOVE.L  D0,(A0)⓪$END;⓪"END SysAlloc;⓪"(*$L=*)⓪ ⓪ ⓪ PROCEDURE DEALLOCATE ( VAR addr: ADDRESS; size: LONGCARD );⓪"BEGIN⓪$IF LONGINT (size) < 0 THEN⓪&size:= MAX (LONGINT)⓪$END;⓪$IF NOT resize (addr, size) THEN⓪&(* versuchen wir's mit StorBase... *)⓪&IF (size # 0) & NOT StorBase.FullStorBaseAccess () THEN⓪((* nichts freigeben *)⓪(RETURN⓪&END;⓪&StorBase.DEALLOCATE (addr, size)⓪$END;⓪"END DEALLOCATE;⓪ ⓪ ⓪ PROCEDURE Available ( size: LONGCARD ): BOOLEAN;⓪ (*⓪"VAR freeBeg, usedBeg: INTEGER;⓪&bl: PtrBlock;⓪&blSize, neededLen: LONGINT;⓪&full: BOOLEAN;⓪ *)⓪"VAR ad: ADDRESS;⓪"BEGIN⓪$(* Alt:⓪(IF getFree (size, neededLen, full, blSize, bl, usedBeg, freeBeg) THEN⓪*RETURN TRUE⓪(ELSE⓪*RETURN StorBase.Available (blSize)⓪(END⓪$*)⓪$(* 29.7.90: *)⓪$ALLOCATE (ad, size);⓪$IF ad = NIL THEN RETURN FALSE END;⓪$DEALLOCATE (ad, 0);⓪$RETURN TRUE⓪"END Available;⓪ ⓪ ⓪ PROCEDURE MemSize ( addr: ADDRESS ): LONGCARD;⓪"VAR hd: PtrHead; bl: PtrBlock; full: BOOLEAN;⓪"BEGIN⓪$IF valid (addr,bl,hd,full) THEN⓪&IF full THEN⓪(RETURN blkSize (bl)⓪&ELSE⓪(RETURN LONG (hd^.size)⓪&END⓪$ELSE⓪&IF StorBase.FullStorBaseAccess () THEN⓪(RETURN StorBase.MemSize (addr)⓪&ELSE⓪(RETURN 0⓪&END⓪$END⓪"END MemSize;⓪ ⓪ ⓪ PROCEDURE MemAvail (): LONGCARD;⓪"VAR l: LONGINT;⓪"BEGIN⓪$(* Aus Programmierfaulheit suchen wir nicht extra in den Blocks⓪%* nach dem größten Block sondern fragen nur StorBase.⓪%*)⓪$l:= INT (StorBase.MemAvail ()) - LONG (BlockSize+BlockFullSize+2);⓪$IF l < 0 THEN l:= 0 END;⓪$RETURN l⓪"END MemAvail;⓪ ⓪ ⓪ PROCEDURE AllAvail (): LONGCARD;⓪"⓪"VAR bl: PtrBlock; av: LONGINT;⓪ ⓪"BEGIN⓪$av:= StorBase.AllAvail ();⓪$bl:= ADR (Root);⓪$LOOP⓪&bl:= ADDRESS (bl^.blk.next);⓪&IF bl = ADR (Root) THEN EXIT END; (* wir haben alle Blocks durch *)⓪&IF NOT blkFull (bl) THEN⓪(av:= av + bl^.free⓪&END;⓪$END;⓪$RETURN av⓪"END AllAvail;⓪ ⓪ ⓪ PROCEDURE Keep ( addr: ADDRESS );⓪"VAR hd: PtrHead; bl: PtrBlock; full: BOOLEAN;⓪"BEGIN⓪$IF valid (addr,bl,hd,full) THEN⓪&IF full THEN⓪(bl^.level:= 0⓪&ELSE⓪(hd^.level:= 0⓪&END⓪$ELSE⓪&StorBase.Keep (addr)⓪$END⓪"END Keep;⓪ ⓪ ⓪ PROCEDURE Enlarge ( VAR addr: ADDRESS; add: LONGCARD; VAR ok: BOOLEAN );⓪"BEGIN⓪$ok:= FALSE;⓪$IF LONGINT (add) >= 0 THEN⓪&IF NOT resize (addr, -LONGINT (add)) THEN⓪(IF StorBase.FullStorBaseAccess () THEN⓪*StorBase.Enlarge (addr, add, ok)⓪(END⓪&ELSE⓪(ok:= TRUE⓪&END⓪$END⓪"END Enlarge;⓪"⓪ ⓪ PROCEDURE TrailAvail (ad: ADDRESS): LONGCARD;⓪"VAR hd: PtrHead; bl: PtrBlock; full: BOOLEAN;⓪"BEGIN⓪$IF valid (ad,bl,hd,full) THEN⓪&RETURN 0 (* !!! hier fehlt was *)⓪$ELSE⓪&RETURN StorBase.TrailAvail (ad)⓪$END;⓪"END TrailAvail;⓪ ⓪ ⓪ PROCEDURE More (id:INTEGER;p:ADDRESS);⓪"(*$L-*)⓪"BEGIN⓪$ASSEMBLER⓪(MOVE.L  -(A3),A0⓪(MOVE.W  -(A3),D0⓪(CMPI.W  #$4EF1,D0⓪(BNE     trail⓪(MOVE.L  (A0)+,(A3)+⓪(MOVE.L  (A0)+,(A3)+⓪(MOVE.L  (A0)+,(A3)+⓪(; Enlarge ( VAR addr: ADDRESS; len: LONGCARD; VAR ok: BOOLEAN );⓪(JMP     Enlarge⓪&trail⓪(CMPI.W  #$4EF2,D0⓪(BNE     getRoot⓪(MOVE.L  (A0)+,(A3)+⓪(MOVE.L  A0,-(A7)⓪(; TrailAvail (ad: ADDRESS): LONGCARD;⓪(JSR     TrailAvail⓪(MOVE.L  (A7)+,A0⓪(MOVE.L  -(A3),(A0)⓪(BRA     ende⓪&getRoot⓪(CMPI.W  #$4EF3,D0⓪(BNE     _verify⓪(MOVE.L  #Root,(A0)⓪(BRA     ende⓪&_verify⓪(CMPI.W  #$4EF4,D0⓪(BNE     _resize⓪(MOVE.L  #Verify,(A0)⓪(BRA     ende⓪&_resize⓪(CMPI.W  #$4EF5,D0⓪(BNE     ende⓪(MOVE.L  #resize,(A0)⓪&ende⓪$END⓪"END More;⓪"(*$L=*)⓪ ⓪ (* --------------------------------- *)⓪ (* --------------------------------- *)⓪ ⓪ PROCEDURE terminate;⓪ ⓪"VAR bl1, bl: PtrBlock; ad: ADDRESS;⓪"VAR usedBeg: INTEGER; hd: PtrHead;⓪ ⓪"(*$L-*)⓪"BEGIN⓪$ASSEMBLER⓪(; bl:= ADDRESS (Root.blk.next);⓪(MOVE.L  Root,A0⓪ ⓪(; LOOP⓪&loopBeg⓪(;   IF bl = ADR (Root) THEN EXIT END; (* wir haben alle Blocks durch *)⓪(CMPA.L  #Root,A0⓪(BEQ     exitLoop⓪(;     bl1:= ADDRESS (bl^.blk.next);⓪(MOVE.L  (A0),A2⓪(;     IF blkFull (bl) THEN⓪(BTST    #6,Block.size(A0)⓪(BEQ     notFull⓪(;       IF bl^.level = StorLevel THEN⓪(MOVE.W  Block.level(A0),D0⓪(CMP.W   StorLevel,D0⓪(BNE     notLev⓪(;         ad:= ADR (bl^.fullData);⓪(;         DEALLOCATE (ad, 0)⓪(PEA     Block.fullData(A0)⓪(MOVE.L  A7,(A3)+⓪(CLR.L   (A3)+⓪(MOVE.L  A2,-(A7)⓪(JSR     DEALLOCATE⓪(MOVE.L  (A7)+,A2⓪(ADDQ.L  #4,A7⓪(;       END⓪¬Lev⓪(BRA       wasFull⓪(;     ELSE⓪¬Full⓪(;     usedBeg:= bl^.hd.n;       (* Start of new used area *)⓪(MOVE.W  Block.hd.n(A0),D0⓪(;     WHILE usedBeg >= 0 DO⓪&whileBeg⓪(TST.W   D0⓪(BMI     whileEnd⓪(;       hd:= abs (bl, usedBeg);⓪(; MOVE.L  A0,A1⓪(; ADDA.W  D0,A1⓪(; ADDA.W  #BlockSize,A1⓪(LEA     BlockSize(A0,D0.W),A1⓪(;       usedBeg:= nextHd (bl, usedBeg);⓪(MOVE.W  Head.hd.n+BlockSize(A0,D0.W),D0⓪(;       IF hd^.level = StorLevel THEN⓪(MOVE.W  Head.level(A1),D1⓪(CMP.W   StorLevel,D1⓪(BNE     notLev2⓪(;         ad:= ADR (hd^.data);⓪(;         DEALLOCATE (ad, 0)⓪(PEA     Head.data(A1)⓪(MOVE.L  A7,(A3)+⓪(CLR.L   (A3)+⓪(MOVEM.L D0/A0/A2,-(A7)⓪(JSR     DEALLOCATE⓪(MOVEM.L (A7)+,D0/A0/A2⓪(ADDQ.L  #4,A7⓪(;       END⓪¬Lev2⓪(;     END⓪(BRA     whileBeg⓪&whileEnd⓪(;   END;⓪&wasFull⓪(;   bl:= bl1⓪(MOVE.L  A2,A0⓪(; END;⓪(BRA     loopBeg⓪&exitLoop⓪(; DEC (StorLevel) (* wird zu Null, wenn Prg terminiert; somit werden *)⓪:(* bei resid. Prgs dann die Allocs wie SysAlloc be-*)⓪:(* handelt; ein neuer Prozeß startet wieder mit    *)⓪:(* Level 1                                         *)⓪(SUBQ.W  #1,StorLevel⓪$END⓪"END terminate;⓪"(*$L=*)⓪ ⓪ (*$L-*)⓪ PROCEDURE chgLevel ( doInc: BOOLEAN; child: BOOLEAN; VAR c: INTEGER );⓪"BEGIN⓪$ASSEMBLER⓪(SUBQ.L  #4,A3⓪(MOVE.L  -(A3),D0⓪(TST     D0              ; child⓪(BEQ     ende⓪(SWAP    D0⓪(TST     D0⓪(BNE     inc⓪(JMP     terminate⓪&inc⓪(ADDQ.W  #1,StorLevel⓪&ende⓪$END⓪"END chgLevel;⓪ (*$L=*)⓪ ⓪ ⓪ VAR ehdl: EnvlpCarrier;⓪$thdl: TermCarrier;⓪$wsp: MemArea;⓪ ⓪ BEGIN (* main *)⓪"WITH Root DO⓪$blk.prev:= ADR (Root);⓪$blk.next:= ADR (Root);⓪$blRov:= NIL⓪"END;⓪"StorLevel:= 1;⓪"IF MaxBlSize = 0L THEN⓪$IF Accessory () THEN⓪&MaxBlSize:= 2048;⓪$ELSE⓪&MaxBlSize:= StorBase.MemAvail () DIV 40L;⓪$END⓪"END;⓪"IF MaxBlSize > $7F00L THEN MaxBlSize:= $7F00 END;⓪"IF ODD (MaxBlSize) THEN DEC (MaxBlSize) END;⓪"CatchProcessTerm (thdl,terminate,wsp);⓪"SetEnvelope (ehdl,chgLevel,wsp);⓪"ASSEMBLER⓪(PEA     X(PC)⓪(MOVE    #38,-(A7)⓪(TRAP    #14⓪(ADDQ.L  #6,A7⓪(BRA     CONT⓪&X MOVE.L  $432,_membot⓪(MOVE.L  $436,_memtop⓪(RTS⓪&CONT⓪"END⓪ END Storage.⓪ ə
  2. (* $000037FC$000031FF$00002535$FFF2EA75$FFF2EA75$FFF2EA75$FFF2EA75$FFF2EA75$FFF2EA75$FFF2EA75$FFF2EA75$FFF2EA75$FFF2EA75$FFF2EA75$FFF2EA75$FFEA6F1B$FFF2EA75$FFF2EA75$FFF2EA75$FFF2EA75$FFF2EA75$FFF2EA75$FFF38B1D$FFF2EA75$FFF2EA75$FFF2EA75$FFF2EA75$FFF2EA75$FFF2EA75$FFF2EA75$FFF2EA75$FFF2EA75$FFF2EA75$FFF2EA75$FFF2EA75$FFF2EA75$FFF41FA4$FFF2EA75$FFF2EA75$FFF2EA75$FFF2EA75$FFF2EA75Ç$000082B0T.......T.......T.......T.......T.......T.......T.......T.......T.......T.......$00008222$000082B0$00007B0E$000082B0$00007B0E$000082B0$FFEC3C8E$FFEC3C8E$FFEC3C8E$00003071$FFEC3C8E$00002A11$0000305E$0000306B$00000EAE$00008544ÿÇâ*)
  3.